package it.okkam.longwell.ui.command;

import it.okkam.webid.model.GetWebID;
import it.okkam.webid.model.VerifyWebID;

import java.io.*;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Vector;

import javax.servlet.ServletException;
import javax.servlet.ServletContext;

import org.apache.log4j.Logger;
import org.apache.velocity.VelocityContext;

import edu.mit.simile.longwell.LongwellServer;
import edu.mit.simile.longwell.login.CheckLogin;
import edu.mit.simile.longwell.login.LoginUtility;
import edu.mit.simile.longwell.ui.FlairMessage;
import edu.mit.simile.longwell.ui.FlairURL;
import edu.mit.simile.longwell.ui.InjectionManager;
import edu.mit.simile.longwell.ui.command.CommandBase;
/**
 * 
 * Webid based authentication and authorization
 *
 */
public class LoginWebidCommand extends CommandBase {
	final static private Logger s_logger = Logger.getLogger(LoginWebidCommand.class);
	CheckLogin check = null;
	final protected String m_template;
	public static boolean userInput = false;
	protected ServletContext context;
	VelocityContext vcContext = null;
	HashMap<String, String> userForSession = new HashMap<String, String>();
	String username;
	/**
	 * @param injectionManager
	 */
	public LoginWebidCommand(InjectionManager injectionManager, String template) {
		super(injectionManager);
		m_template = template;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.mit.simile.flair.IFlairCommand#execute(edu.mit.simile.flair.FlairMessage
	 * )
	 */
	/**
	 * Retrieve the webid, modulus and exponent from a certificate, if the user has provided.
	 */
	
	public void execute(FlairMessage msg) throws ServletException {

		X509Certificate[] certificates = (X509Certificate[]) msg.m_request
				.getAttribute("javax.servlet.request.X509Certificate");

		if (certificates != null) {
			boolean found = false;
			Vector webID = null;
			Vector modulus = null;
			Vector exponent = null;
			if (certificates != null) {
				System.out.println("Certeficate found");
				GetWebID webIDComponents = new GetWebID(certificates);
				webID = webIDComponents.getWebID();
				modulus = webIDComponents.getModules();
				exponent = webIDComponents.getExponent();

				if (webID != null && webID.size() > 0)
					found = true;
			}
			// if there is webID in the certificate
			if (found) {
				VerifyWebID verifyWebID = new VerifyWebID();
				context = msg.m_servlet.getServletContext();
				String userListFileName = LongwellServer.getUsersDatasetPath(); 
				/*
				 * Send the webid (webID.firstElement()) to the rdf store and check if the user is valid one
				 */
				boolean allowed = verifyWebID.isAllowed(webID.firstElement().toString(), userListFileName);
				boolean authenticated = false;
				
				
				if (allowed) {
					
					username = verifyWebID.getUserName(webID.firstElement().toString(), userListFileName);
					
					//save the login with date and username into the triplestore
					LoginUtility.saveLogin(username);
					
					msg.getProfile().setUsername(username);
					authenticated = verifyWebID.isAuthenticated(webID
							.firstElement().toString(), modulus.firstElement()
							.toString(), exponent.firstElement().toString(),
							webID.firstElement().toString());
				}
				
				//webid is not allowed for login	
				else {
					try {
						vcContext = createContext(msg);
						vcContext.put("application", "BCC - Login");
						// vcContext.put("error", error);
						userForSession.put(msg.m_request.getSession().getId(),
								"invalid_webid");
						vcContext.put("sessionId", msg.m_request.getSession()
								.getId());
						vcContext.put("hashError", userForSession);
						msg.m_ve.mergeTemplate(m_template, vcContext,
								msg.m_response.getWriter());
						userInput = true;

					} catch (Exception e) {
						s_logger.error(e);
						e.printStackTrace();
					}
				}
				
				//webid is authenticated				
				if (allowed && authenticated) {
					try {
						s_logger.info("********************The user " +username +" has done the WebID login************************");
						msg.m_response.sendRedirect(new FlairURL(msg)
								.changeCommandQuery("selectDataset", "")
								.toURLString());
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						}
					}
				
				
				//webid is not authenticated for login
				else if (allowed && !authenticated){
					try {
						vcContext = createContext(msg);
						vcContext.put("application", "BCC - Login");
						// vcContext.put("error", error);
						userForSession.put(msg.m_request.getSession().getId(),
								"invalid_webid");
						vcContext.put("sessionId", msg.m_request.getSession()
								.getId());
						vcContext.put("hashError", userForSession);
						msg.m_ve.mergeTemplate(m_template, vcContext,
								msg.m_response.getWriter());
						userInput = true;

					} catch (Exception e) {
						s_logger.error(e);
						e.printStackTrace();
					}
				}
			}
				
			//there is no webid in the certificate
			else {
				
				try {
					vcContext = createContext(msg);
					vcContext.put("application", "BCC - Login");
					// vcContext.put("error", error);
					userForSession.put(msg.m_request.getSession().getId(),
							"no_webid");
					vcContext.put("sessionId", msg.m_request.getSession()
							.getId());
					vcContext.put("hashError", userForSession);
					msg.m_ve.mergeTemplate(m_template, vcContext,
							msg.m_response.getWriter());
					userInput = true;

				} catch (Exception e) {
					s_logger.error(e);
					e.printStackTrace();
				}
								
			}
		}
		
		
		//If there is no certificate provided, redirect back to home page. 
		//Inform the user to import her certificate to the browser.  
		else {
			
			try {
				vcContext = createContext(msg);
				vcContext.put("application", "BCC - Login");
				// vcContext.put("error", error);
				userForSession.put(msg.m_request.getSession().getId(),
						"certificate_null");
				vcContext.put("sessionId", msg.m_request.getSession()
						.getId());
				vcContext.put("hashError", userForSession);
				msg.m_ve.mergeTemplate(m_template, vcContext,
						msg.m_response.getWriter());
				userInput = true;

			} catch (Exception e) {
				s_logger.error(e);
				e.printStackTrace();
			}
			
		}
	}
}
